﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Z1029.NoteEditor
{
    public class NoteSetter : MonoBehaviour
    {
        public Camera cam;
        public RectTransform re;
        public NoteGlobalView.NoteSetter sync;
        public NoteType targetSetType;
        public Note.Direction direction;
        public float PosX;
        public float Speed;
        [Tooltip("几分之一拍一个note（自动取整）")] public int setNoteRoundBeat;
        [Tooltip("如果是Hold需要设置")] public int holdTime;
        public bool useMouse;
        public int mouseSetPos;
        public int judgelineIndex;
        public bool continuedGenerate;
        public bool attachToBeatline;
        float lastTime;
        public KeyCode GenerateKey;
        public KeyCode continuedGenerateKey;
        private void Start()
        {
            cam = LevelController.instance.viewCam;
            sync = FindObjectOfType<NoteGlobalView.NoteSetter>();
        }
        void Update()
        {
            setNoteRoundBeat = LevelController.instance.nowDensity;
            if ((((Input.GetMouseButton(0) && mouseSetPos == 1) || mouseSetPos == 2)) && mouseSetPos != 0 && CanGenerateNote())
            {
                PosX = TransformUtils.GetLocalPosition(
                    new Vector3(cam.ScreenToWorldPoint(
                        new Vector3(
                            Input.mousePosition.x - RectToMouse(re).x, 
                            Input.mousePosition.y - RectToMouse(re).y, 
                            LevelController.instance.camDistance)).x, 
                    cam.ScreenToWorldPoint(
                            new Vector3(
                                Input.mousePosition.x - RectToMouse(re).x, 
                                Input.mousePosition.y - RectToMouse(re).y, 8)).y, 
                                0), 
                    LevelController.instance.judgelines[judgelineIndex].transform).x;
                if (LevelController.instance.showTrackLine) PosX = Mathf.Round(PosX / LevelController.instance.tracklineDensity) * LevelController.instance.tracklineDensity;
            }
            if (Input.GetKeyDown(GenerateKey) || (useMouse && Input.GetMouseButtonDown(0) && CanGenerateNote()))
            {
                if (!continuedGenerate)
                {
                    GenerateNote();
                }
            }
            if (Input.GetKey(GenerateKey) || (useMouse && Input.GetMouseButton(0) && CanGenerateNote()))
            {
                if (continuedGenerate)
                {
                    if (Mathf.RoundToInt(LevelController.instance.NowBeatTime / setNoteRoundBeat) * setNoteRoundBeat - lastTime > 1 / 32 * setNoteRoundBeat)
                    {
                        NoteGlobalView.Note.NoteData data = new NoteGlobalView.Note.NoteData();
                        data.type = (NoteGlobalView.NoteType)targetSetType;
                        data.positionX = PosX;
                        data.speed = Speed*12;
                        data.beatTime = Mathf.RoundToInt(LevelController.instance.NowBeatTime / setNoteRoundBeat) * setNoteRoundBeat;
                        data.beatHoldTime = holdTime;
                        lastTime = data.beatTime;
                        LevelController.instance.notesManager.InstantiateNote(
                            NoteGlobalView.LevelController.instance.notesManager.InstantiateNote(
                                (NoteGlobalView.NoteType)targetSetType,
                                data, 
                                NoteGlobalView.JudgementLine.selectedJudgeline, 
                                (NoteGlobalView.Note.Direction)direction),
                            LevelController.instance.judgelines[0]
                            );
                    }
                }
            }
            CheckHotKey();
        }

        public void CheckHotKey()
        {
            if (Input.GetKeyDown(KeyCode.Z))
            {
                NoteType tp = targetSetType;
                targetSetType = NoteType.Click;
                GenerateNote();
                targetSetType = tp;
            }
            if (Input.GetKeyDown(KeyCode.X))
            {
                NoteType tp = targetSetType;
                targetSetType = NoteType.Drag;
                GenerateNote();
                targetSetType = tp;
            }
            if (Input.GetKeyDown(KeyCode.C))
            {
                NoteType tp = targetSetType;
                targetSetType = NoteType.Flick;
                GenerateNote();
                targetSetType = tp;
            }
            if (Input.GetKeyDown(KeyCode.V))
            {
                NoteType tp = targetSetType;
                targetSetType = NoteType.Hold;
                NoteGlobalView.Note hh;
                Note h = GenerateNote(out hh);
                targetSetType = tp;
                StartCoroutine(SetHold(h,hh));
            }
        }

        IEnumerator SetHold(Note h, NoteGlobalView.Note hh)
        {
            bool a = false;
            for (; ; )
            {
                if (Input.anyKeyDown)
                {
                    if (a) break;
                    else a = true;
                }


                //Debug.Log("114514");
                float posY = new Vector3(
                    cam.ScreenToWorldPoint(
                        new Vector3(
                            Input.mousePosition.x - RectToMouse(re).x, 
                            Input.mousePosition.y - RectToMouse(re).y, 
                            LevelController.instance.camDistance)
                            ).x, 
                    cam.ScreenToWorldPoint(
                        new Vector3(
                            Input.mousePosition.x - RectToMouse(re).x, 
                            Input.mousePosition.y - RectToMouse(re).y, 
                            8)).y,
                    0).y;
                int newT = Utils.GetBeatTimeFromTime(LevelController.instance.judgelines[0].DistanceToTime(posY, h.direction == Note.Direction.Below), LevelController.instance.judgelines[0].bpm);
                newT = Mathf.RoundToInt(newT / (LevelController.instance.nowDensity)) * (LevelController.instance.nowDensity);
                //if (ViewCtrl.viewType == ViewCtrl.ViewType.Move) selectNote.noteData.beatTime = newT;
                h.noteData.beatHoldTime = newT - h.noteData.beatTime;
                hh.noteData.beatHoldTime = newT - hh.noteData.beatTime;
                yield return null;
            }
            yield return null;
        }

        public Note GenerateNote()
        {
            float posY = new Vector3(cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - RectToMouse(re).x, Input.mousePosition.y - RectToMouse(re).y, LevelController.instance.camDistance)).x, cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - RectToMouse(re).x, Input.mousePosition.y - RectToMouse(re).y, 8)).y, 0).y;
            int newT = Utils.GetBeatTimeFromTime(LevelController.instance.judgelines[0].DistanceToTime(posY, direction == Note.Direction.Below), LevelController.instance.judgelines[0].bpm);
            if (attachToBeatline) newT = Mathf.RoundToInt(newT / (LevelController.instance.nowDensity)) * (LevelController.instance.nowDensity);
            Note.NoteData data = new Note.NoteData();
            data.type = targetSetType;
            data.positionX = PosX;
            data.speed = Speed*12;

            data.beatTime = newT;
            data.beatHoldTime = holdTime;
            Note n = LevelController.instance.notesManager.InstantiateNote(targetSetType, data, LevelController.instance.judgelines[judgelineIndex], direction);
            return n;
        }

        public Note GenerateNote(out NoteGlobalView.Note note)
        {
            float posY = new Vector3(cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - RectToMouse(re).x, Input.mousePosition.y - RectToMouse(re).y, LevelController.instance.camDistance)).x, cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - RectToMouse(re).x, Input.mousePosition.y - RectToMouse(re).y, 8)).y, 0).y;
            int newT = Utils.GetBeatTimeFromTime(LevelController.instance.judgelines[0].DistanceToTime(posY, direction == Note.Direction.Below), LevelController.instance.judgelines[0].bpm);
            if (attachToBeatline) newT = Mathf.RoundToInt(newT / (LevelController.instance.nowDensity)) * (LevelController.instance.nowDensity);
            Note.NoteData data = new Note.NoteData();
            data.type = targetSetType;
            data.positionX = PosX;
            data.speed = Speed*12;

            data.beatTime = newT;
            data.beatHoldTime = holdTime;
            Note n = LevelController.instance.notesManager.InstantiateNote(targetSetType, data, LevelController.instance.judgelines[judgelineIndex], direction);
            NoteGlobalView.Note nn = n.targetNote;
            note = nn;
            return n;
        }

        public bool CanGenerateNote()
        {
            return Input.mousePosition.x - RectToMouse(re).x < re.sizeDelta.x && Input.mousePosition.x - RectToMouse(re).x > 0;
        }

        public Vector2 RectToMouse(RectTransform rect)
        {
            Vector2 res = Vector2.zero;
            res.x = rect.anchoredPosition.x + Screen.width / 2 - rect.sizeDelta.x / 2;
            res.y = rect.anchoredPosition.y + Screen.height / 2 - rect.sizeDelta.y / 2;
            return res;
        }
    }
}